// Copyright 2021 ETH Zurich and University of Bologna.
// Solderpad Hardware License, Version 0.51, see LICENSE for details.
// SPDX-License-Identifier: SHL-0.51
//
// Author: Matteo Perotti <mperotti@iis.ee.ethz.ch>
//         Basile Bougenot <bbougenot@student.ethz.ch>

#include "vector_macros.h"
#include "float_macros.h"

// Simple random test with similar values
void TEST_CASE1(void) {
  VSET(16, e16, m1);
  //               0.3784,  0.9043, -0.4600, -0.6748,  0.4448,  0.8804,  0.1497,  0.7285,  0.9927,  0.9922,  0.8965,  0.8672, -0.1860,  0.9336, -0.2959,  0.9668
  VLOAD_16(v2,     0x360e,  0x3b3c,  0xb75c,  0xb966,  0x371e,  0x3b0b,  0x30ca,  0x39d4,  0x3bf1,  0x3bf0,  0x3b2c,  0x3af0,  0xb1f4,  0x3b78,  0xb4bc,  0x3bbc);
  //              -0.7988, -0.5054, -0.9380, -0.7383, -0.7168,  0.2181, -0.1597,  0.1833,  0.0045, -0.2152,  0.1919, -0.6914,  0.1748, -0.8604,  0.6084,  0.1591
  VLOAD_16(v3,     0xba64,  0xb80b,  0xbb81,  0xb9e8,  0xb9bc,  0x32fb,  0xb11c,  0x31de,  0x1c8f,  0xb2e3,  0x3224,  0xb988,  0x3198,  0xbae2,  0x38de,  0x3117);
  asm volatile("vfsgnj.vv v1, v2, v3");
  //              -0.3784, -0.9043, -0.4600, -0.6748, -0.4448,  0.8804, -0.1497,  0.7285,  0.9927, -0.9922,  0.8965, -0.8672,  0.1860, -0.9336,  0.2959,  0.9668
  VCMP_U16(1, v1,  0xb60e,  0xbb3c,  0xb75c,  0xb966,  0xb71e,  0x3b0b,  0xb0ca,  0x39d4,  0x3bf1,  0xbbf0,  0x3b2c,  0xbaf0,  0x31f4,  0xbb78,  0x34bc,  0x3bbc);

  VSET(16, e32, m1);
  //               0.30226409,  0.06318295, -0.82590002, -0.17829193,  0.45379546,  0.85831785, -0.43186289, -0.32250872,  0.35404092, -0.55081791,  0.09124859, -0.13254598,  0.95786512,  0.95395225,  0.19890578,  0.76956910
  VLOAD_32(v2,     0x3e9ac25c,  0x3d816610,  0xbf536e2f,  0xbe369229,  0x3ee857e1,  0x3f5bbab8,  0xbedd1d22,  0xbea51fdd,  0x3eb544da,  0xbf0d0267,  0x3dbae08b,  0xbe07ba22,  0x3f7536a6,  0x3f743637,  0x3e4badf5,  0x3f45027b);
  //               0.06560040,  0.31805936,  0.14663234, -0.85004497, -0.49171701,  0.32139263, -0.09995110, -0.34368968,  0.33917251,  0.07372360,  0.70147520,  0.82915747, -0.14581841, -0.19974701, -0.58837658,  0.95794803
  VLOAD_32(v3,     0x3d865981,  0x3ea2d8ad,  0x3e1626ca,  0xbf599c8c,  0xbefbc255,  0x3ea48d93,  0xbdccb329,  0xbeaff818,  0x3eada805,  0x3d96fc66,  0x3f3393e1,  0x3f5443aa,  0xbe15516c,  0xbe4c8a7b,  0xbf169fd9,  0x3f753c15);
  asm volatile("vfsgnj.vv v1, v2, v3");
  //               0.30226409,  0.06318295,  0.82590002, -0.17829193, -0.45379546,  0.85831785, -0.43186289, -0.32250872,  0.35404092,  0.55081791,  0.09124859,  0.13254598, -0.95786512, -0.95395225, -0.19890578,  0.76956910
  VCMP_U32(2, v1,  0x3e9ac25c,  0x3d816610,  0x3f536e2f,  0xbe369229,  0xbee857e1,  0x3f5bbab8,  0xbedd1d22,  0xbea51fdd,  0x3eb544da,  0x3f0d0267,  0x3dbae08b,  0x3e07ba22,  0xbf7536a6,  0xbf743637,  0xbe4badf5,  0x3f45027b);

  VSET(16, e64, m1);
  //              -0.1900636538602862, -0.9484843154859770,  0.5869658512198073,  0.4707187701595239,  0.1954104859873083,  0.0486819373954939, -0.1899986048192088, -0.1837438621239862,  0.2694105234528963, -0.7960262036276018,  0.6381040017115214,  0.2199215324293253,  0.4219965521278597, -0.6541697303087526,  0.7254411745966671,  0.2439726910863504
  VLOAD_64(v2,     0xbfc854017cbe7d20,  0xbfee59fbc778ffbc,  0x3fe2c86c9bdb73b4,  0x3fde20419edcb428,  0x3fc90335f74e33c8,  0x3fa8ecd6c20a0480,  0xbfc851dfd0fdf7f8,  0xbfc784eb3b54e580,  0x3fd13e05a2db6b68,  0xbfe9790bf1eadde4,  0x3fe46b59155986dc,  0x3fcc266386bc2e10,  0x3fdb01fdd39a7d9c,  0xbfe4eef55bb6b208,  0x3fe736d06902107a,  0x3fcf3a7f44aa9f48);
  //               0.0713540199640168,  0.3499800646587572, -0.5478360240866667, -0.7324007835973676,  0.5646664961108800, -0.7430380608733607, -0.5676032662558192, -0.7382565525776155, -0.7933198466305424, -0.0650991402083496, -0.1766522935757786, -0.4663829943595241, -0.1565231028144627, -0.0629224333525875, -0.9086692399439535, -0.1206057821437510
  VLOAD_64(v3,     0x3fb24441ce2eff50,  0x3fd66612c8fd8664,  0xbfe187df69e0bb9c,  0xbfe76fd3c4a3b1e8,  0x3fe211bf78be2e36,  0xbfe7c6f7c1644c86,  0xbfe229ce53357d20,  0xbfe79fcc34ac1d30,  0xbfe962e04d917824,  0xbfb0aa5656314cf0,  0xbfc69c8ad7d5ef20,  0xbfddd9380f0bd244,  0xbfc408f2f3d40a40,  0xbfb01baf416f2160,  0xbfed13d1838e183a,  0xbfbee005420412c0);
  asm volatile("vfsgnj.vv v1, v2, v3");
  //               0.1900636538602862,  0.9484843154859770, -0.5869658512198073, -0.4707187701595239,  0.1954104859873083, -0.0486819373954939, -0.1899986048192088, -0.1837438621239862, -0.2694105234528963, -0.7960262036276018, -0.6381040017115214, -0.2199215324293253, -0.4219965521278597, -0.6541697303087526, -0.7254411745966671, -0.2439726910863504
  VCMP_U64(3, v1,  0x3fc854017cbe7d20,  0x3fee59fbc778ffbc,  0xbfe2c86c9bdb73b4,  0xbfde20419edcb428,  0x3fc90335f74e33c8,  0xbfa8ecd6c20a0480,  0xbfc851dfd0fdf7f8,  0xbfc784eb3b54e580,  0xbfd13e05a2db6b68,  0xbfe9790bf1eadde4,  0xbfe46b59155986dc,  0xbfcc266386bc2e10,  0xbfdb01fdd39a7d9c,  0xbfe4eef55bb6b208,  0xbfe736d06902107a,  0xbfcf3a7f44aa9f48);
};

// Simple random test with similar values (masked)
// The numbers are the same of TEST_CASE1
void TEST_CASE2(void) {
  VSET(16, e16, m1);
  //               0.3784,  0.9043, -0.4600, -0.6748,  0.4448,  0.8804,  0.1497,  0.7285,  0.9927,  0.9922,  0.8965,  0.8672, -0.1860,  0.9336, -0.2959,  0.9668
  VLOAD_16(v2,     0x360e,  0x3b3c,  0xb75c,  0xb966,  0x371e,  0x3b0b,  0x30ca,  0x39d4,  0x3bf1,  0x3bf0,  0x3b2c,  0x3af0,  0xb1f4,  0x3b78,  0xb4bc,  0x3bbc);
  //              -0.7988, -0.5054, -0.9380, -0.7383, -0.7168,  0.2181, -0.1597,  0.1833,  0.0045, -0.2152,  0.1919, -0.6914,  0.1748, -0.8604,  0.6084,  0.1591
  VLOAD_16(v3,     0xba64,  0xb80b,  0xbb81,  0xb9e8,  0xb9bc,  0x32fb,  0xb11c,  0x31de,  0x1c8f,  0xb2e3,  0x3224,  0xb988,  0x3198,  0xbae2,  0x38de,  0x3117);
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vfsgnj.vv v1, v2, v3, v0.t");
  //               0.0000, -0.9043,  0.0000, -0.6748,  0.0000,  0.8804,  0.0000,  0.7285,  0.0000, -0.9922,  0.0000, -0.8672,  0.0000, -0.9336,  0.0000,  0.9668
  VCMP_U16(4, v1,  0x0,  0xbb3c,  0x0,  0xb966,  0x0,  0x3b0b,  0x0,  0x39d4,  0x0,  0xbbf0,  0x0,  0xbaf0,  0x0,  0xbb78,  0x0,  0x3bbc);

  VSET(16, e32, m1);
  //               0.30226409,  0.06318295, -0.82590002, -0.17829193,  0.45379546,  0.85831785, -0.43186289, -0.32250872,  0.35404092, -0.55081791,  0.09124859, -0.13254598,  0.95786512,  0.95395225,  0.19890578,  0.76956910
  VLOAD_32(v2,     0x3e9ac25c,  0x3d816610,  0xbf536e2f,  0xbe369229,  0x3ee857e1,  0x3f5bbab8,  0xbedd1d22,  0xbea51fdd,  0x3eb544da,  0xbf0d0267,  0x3dbae08b,  0xbe07ba22,  0x3f7536a6,  0x3f743637,  0x3e4badf5,  0x3f45027b);
  //               0.06560040,  0.31805936,  0.14663234, -0.85004497, -0.49171701,  0.32139263, -0.09995110, -0.34368968,  0.33917251,  0.07372360,  0.70147520,  0.82915747, -0.14581841, -0.19974701, -0.58837658,  0.95794803
  VLOAD_32(v3,     0x3d865981,  0x3ea2d8ad,  0x3e1626ca,  0xbf599c8c,  0xbefbc255,  0x3ea48d93,  0xbdccb329,  0xbeaff818,  0x3eada805,  0x3d96fc66,  0x3f3393e1,  0x3f5443aa,  0xbe15516c,  0xbe4c8a7b,  0xbf169fd9,  0x3f753c15);
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vfsgnj.vv v1, v2, v3, v0.t");
  //               0.00000000,  0.06318295,  0.00000000, -0.17829193,  0.00000000,  0.85831785,  0.00000000, -0.32250872,  0.00000000,  0.55081791,  0.00000000,  0.13254598,  0.00000000, -0.95395225,  0.00000000,  0.76956910
  VCMP_U32(5, v1,  0x0,  0x3d816610,  0x0,  0xbe369229,  0x0,  0x3f5bbab8,  0x0,  0xbea51fdd,  0x0,  0x3f0d0267,  0x0,  0x3e07ba22,  0x0,  0xbf743637,  0x0,  0x3f45027b);

  VSET(16, e64, m1);
  //              -0.1900636538602862, -0.9484843154859770,  0.5869658512198073,  0.4707187701595239,  0.1954104859873083,  0.0486819373954939, -0.1899986048192088, -0.1837438621239862,  0.2694105234528963, -0.7960262036276018,  0.6381040017115214,  0.2199215324293253,  0.4219965521278597, -0.6541697303087526,  0.7254411745966671,  0.2439726910863504
  VLOAD_64(v2,     0xbfc854017cbe7d20,  0xbfee59fbc778ffbc,  0x3fe2c86c9bdb73b4,  0x3fde20419edcb428,  0x3fc90335f74e33c8,  0x3fa8ecd6c20a0480,  0xbfc851dfd0fdf7f8,  0xbfc784eb3b54e580,  0x3fd13e05a2db6b68,  0xbfe9790bf1eadde4,  0x3fe46b59155986dc,  0x3fcc266386bc2e10,  0x3fdb01fdd39a7d9c,  0xbfe4eef55bb6b208,  0x3fe736d06902107a,  0x3fcf3a7f44aa9f48);
  //               0.0713540199640168,  0.3499800646587572, -0.5478360240866667, -0.7324007835973676,  0.5646664961108800, -0.7430380608733607, -0.5676032662558192, -0.7382565525776155, -0.7933198466305424, -0.0650991402083496, -0.1766522935757786, -0.4663829943595241, -0.1565231028144627, -0.0629224333525875, -0.9086692399439535, -0.1206057821437510
  VLOAD_64(v3,     0x3fb24441ce2eff50,  0x3fd66612c8fd8664,  0xbfe187df69e0bb9c,  0xbfe76fd3c4a3b1e8,  0x3fe211bf78be2e36,  0xbfe7c6f7c1644c86,  0xbfe229ce53357d20,  0xbfe79fcc34ac1d30,  0xbfe962e04d917824,  0xbfb0aa5656314cf0,  0xbfc69c8ad7d5ef20,  0xbfddd9380f0bd244,  0xbfc408f2f3d40a40,  0xbfb01baf416f2160,  0xbfed13d1838e183a,  0xbfbee005420412c0);
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vfsgnj.vv v1, v2, v3, v0.t");
  //               0.0000000000000000,  0.9484843154859770,  0.0000000000000000, -0.4707187701595239,  0.0000000000000000, -0.0486819373954939,  0.0000000000000000, -0.1837438621239862,  0.0000000000000000, -0.7960262036276018,  0.0000000000000000, -0.2199215324293253,  0.0000000000000000, -0.6541697303087526,  0.0000000000000000, -0.2439726910863504
  VCMP_U64(6, v1,  0x0,  0x3fee59fbc778ffbc,  0x0,  0xbfde20419edcb428,  0x0,  0xbfa8ecd6c20a0480,  0x0,  0xbfc784eb3b54e580,  0x0,  0xbfe9790bf1eadde4,  0x0,  0xbfcc266386bc2e10,  0x0,  0xbfe4eef55bb6b208,  0x0,  0xbfcf3a7f44aa9f48);
};

// Simple random test with similar values (vector-scalar)
void TEST_CASE3(void) {
  VSET(16, e16, m1);
  double dscalar_16;
  //                              0.9023
  BOX_HALF_IN_DOUBLE(dscalar_16,  0x3b38);
  //               0.5586,  0.0221,  0.7397,  0.9844, -0.1426,  0.6958,  0.0319,  0.3943, -0.5425,  0.9814,  0.7852, -0.7271, -0.1810, -0.7485, -0.3499, -0.2178
  VLOAD_16(v2,     0x3878,  0x25a7,  0x39eb,  0x3be0,  0xb090,  0x3991,  0x2816,  0x364f,  0xb857,  0x3bda,  0x3a48,  0xb9d1,  0xb1cb,  0xb9fd,  0xb599,  0xb2f8);
  asm volatile("vfsgnj.vf v1, v2, %[A]" :: [A] "f" (dscalar_16));
  //               0.5586,  0.0221,  0.7397,  0.9844,  0.1426,  0.6958,  0.0319,  0.3943,  0.5425,  0.9814,  0.7852,  0.7271,  0.1810,  0.7485,  0.3499,  0.2178
  VCMP_U16(7, v1,  0x3878,  0x25a7,  0x39eb,  0x3be0,  0x3090,  0x3991,  0x2816,  0x364f,  0x3857,  0x3bda,  0x3a48,  0x39d1,  0x31cb,  0x39fd,  0x3599,  0x32f8);

  VSET(16, e32, m1);
  double dscalar_32;
  //                               0.64529878
  BOX_FLOAT_IN_DOUBLE(dscalar_32,  0x3f25324d);
  //               0.27794743,  0.64720273,  0.88201439, -0.27750894, -0.02381280, -0.27677080, -0.58998328,  0.15329099,  0.52908343, -0.63265759,  0.48432603,  0.70191479, -0.55785930,  0.34719029, -0.06872076, -0.69960916
  VLOAD_32(v2,     0x3e8e4f20,  0x3f25af14,  0x3f61cbb2,  0xbe8e15a7,  0xbcc31310,  0xbe8db4e7,  0xbf170925,  0x3e1cf850,  0x3f077203,  0xbf21f5d9,  0x3ef7f995,  0x3f33b0b0,  0xbf0ecfde,  0x3eb1c2ed,  0xbd8cbd78,  0xbf331996);
  asm volatile("vfsgnj.vf v1, v2, %[A]" :: [A] "f" (dscalar_32));
  //               0.27794743,  0.64720273,  0.88201439,  0.27750894,  0.02381280,  0.27677080,  0.58998328,  0.15329099,  0.52908343,  0.63265759,  0.48432603,  0.70191479,  0.55785930,  0.34719029,  0.06872076,  0.69960916
  VCMP_U32(8, v1,  0x3e8e4f20,  0x3f25af14,  0x3f61cbb2,  0x3e8e15a7,  0x3cc31310,  0x3e8db4e7,  0x3f170925,  0x3e1cf850,  0x3f077203,  0x3f21f5d9,  0x3ef7f995,  0x3f33b0b0,  0x3f0ecfde,  0x3eb1c2ed,  0x3d8cbd78,  0x3f331996);

  VSET(16, e64, m1);
  double dscalar_64;
  //                                0.4863995754678485
  BOX_DOUBLE_IN_DOUBLE(dscalar_64,  0x3fdf212baf5b0d68);
  //                0.4577518787562838, -0.0989909265811582, -0.5406373582107198, -0.6896639688670565,  0.9053190721589099, -0.7617679756965072,  0.4649312111760273,  0.6917063611214438,  0.2205644023843889,  0.1217272698758698, -0.3345487709580650,  0.1693366988903542,  0.4095982059989967,  0.7157757577569959, -0.5339346851091937,  0.4946553559543683
  VLOAD_64(v2,      0x3fdd4bce893c3600,  0xbfb9577828444dc0,  0xbfe14ce6b790591e,  0xbfe611ba2bf06f2a,  0x3fecf85fb3ebc33c,  0xbfe860673bd8363e,  0x3fddc16ed6b90158,  0x3fe6227560ee74e0,  0x3fcc3b744f738cd0,  0x3fbf2984b325f230,  0xbfd5693f3f8ba3fc,  0x3fc5acd32fdf92e8,  0x3fda36db64d10584,  0x3fe6e7a28fdabfd2,  0xbfe115fe3157cf38,  0x3fdfa86ef0276044);
  asm volatile("vfsgnj.vf v1, v2, %[A]" :: [A] "f" (dscalar_64));
  //               0.4577518787562838,  0.0989909265811582,  0.5406373582107198,  0.6896639688670565,  0.9053190721589099,  0.7617679756965072,  0.4649312111760273,  0.6917063611214438,  0.2205644023843889,  0.1217272698758698,  0.3345487709580650,  0.1693366988903542,  0.4095982059989967,  0.7157757577569959,  0.5339346851091937,  0.4946553559543683
  VCMP_U64(9, v1,  0x3fdd4bce893c3600,  0x3fb9577828444dc0,  0x3fe14ce6b790591e,  0x3fe611ba2bf06f2a,  0x3fecf85fb3ebc33c,  0x3fe860673bd8363e,  0x3fddc16ed6b90158,  0x3fe6227560ee74e0,  0x3fcc3b744f738cd0,  0x3fbf2984b325f230,  0x3fd5693f3f8ba3fc,  0x3fc5acd32fdf92e8,  0x3fda36db64d10584,  0x3fe6e7a28fdabfd2,  0x3fe115fe3157cf38,  0x3fdfa86ef0276044);
};

// Simple random test with similar values (vector-scalar) (masked)
void TEST_CASE4(void) {
  VSET(16, e16, m1);
  double dscalar_16;
  //                              0.9023
  BOX_HALF_IN_DOUBLE(dscalar_16,  0x3b38);
  //                0.5586,  0.0221,  0.7397,  0.9844, -0.1426,  0.6958,  0.0319,  0.3943, -0.5425,  0.9814,  0.7852, -0.7271, -0.1810, -0.7485, -0.3499, -0.2178
  VLOAD_16(v2,      0x3878,  0x25a7,  0x39eb,  0x3be0,  0xb090,  0x3991,  0x2816,  0x364f,  0xb857,  0x3bda,  0x3a48,  0xb9d1,  0xb1cb,  0xb9fd,  0xb599,  0xb2f8);
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vfsgnj.vf v1, v2, %[A], v0.t" :: [A] "f" (dscalar_16));
  //                0.0000,  0.0221,  0.0000,  0.9844,  0.0000,  0.6958,  0.0000,  0.3943,  0.0000,  0.9814,  0.0000,  0.7271,  0.0000,  0.7485,  0.0000,  0.2178
  VCMP_U16(10, v1,  0x0,  0x25a7,  0x0,  0x3be0,  0x0,  0x3991,  0x0,  0x364f,  0x0,  0x3bda,  0x0,  0x39d1,  0x0,  0x39fd,  0x0,  0x32f8);

  VSET(16, e32, m1);
  double dscalar_32;
  //                               0.64529878
  BOX_FLOAT_IN_DOUBLE(dscalar_32,  0x3f25324d);
  //                0.27794743,  0.64720273,  0.88201439, -0.27750894, -0.02381280, -0.27677080, -0.58998328,  0.15329099,  0.52908343, -0.63265759,  0.48432603,  0.70191479, -0.55785930,  0.34719029, -0.06872076, -0.69960916
  VLOAD_32(v2,      0x3e8e4f20,  0x3f25af14,  0x3f61cbb2,  0xbe8e15a7,  0xbcc31310,  0xbe8db4e7,  0xbf170925,  0x3e1cf850,  0x3f077203,  0xbf21f5d9,  0x3ef7f995,  0x3f33b0b0,  0xbf0ecfde,  0x3eb1c2ed,  0xbd8cbd78,  0xbf331996);
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vfsgnj.vf v1, v2, %[A], v0.t" :: [A] "f" (dscalar_32));
  //                0.00000000,  0.64720273,  0.00000000,  0.27750894,  0.00000000,  0.27677080,  0.00000000,  0.15329099,  0.00000000,  0.63265759,  0.00000000,  0.70191479,  0.00000000,  0.34719029,  0.00000000,  0.69960916
  VCMP_U32(11, v1,  0x0,  0x3f25af14,  0x0,  0x3e8e15a7,  0x0,  0x3e8db4e7,  0x0,  0x3e1cf850,  0x0,  0x3f21f5d9,  0x0,  0x3f33b0b0,  0x0,  0x3eb1c2ed,  0x0,  0x3f331996);

  VSET(16, e64, m1);
  double dscalar_64;
  //                                0.4863995754678485
  BOX_DOUBLE_IN_DOUBLE(dscalar_64,  0x3fdf212baf5b0d68);
  //                 0.4577518787562838, -0.0989909265811582, -0.5406373582107198, -0.6896639688670565,  0.9053190721589099, -0.7617679756965072,  0.4649312111760273,  0.6917063611214438,  0.2205644023843889,  0.1217272698758698, -0.3345487709580650,  0.1693366988903542,  0.4095982059989967,  0.7157757577569959, -0.5339346851091937,  0.4946553559543683
  VLOAD_64(v2,       0x3fdd4bce893c3600,  0xbfb9577828444dc0,  0xbfe14ce6b790591e,  0xbfe611ba2bf06f2a,  0x3fecf85fb3ebc33c,  0xbfe860673bd8363e,  0x3fddc16ed6b90158,  0x3fe6227560ee74e0,  0x3fcc3b744f738cd0,  0x3fbf2984b325f230,  0xbfd5693f3f8ba3fc,  0x3fc5acd32fdf92e8,  0x3fda36db64d10584,  0x3fe6e7a28fdabfd2,  0xbfe115fe3157cf38,  0x3fdfa86ef0276044);
  VLOAD_8(v0, 0xAA, 0xAA);
  VCLEAR(v1);
  asm volatile("vfsgnj.vf v1, v2, %[A], v0.t" :: [A] "f" (dscalar_64));
  //                0.0000000000000000,  0.0989909265811582,  0.0000000000000000,  0.6896639688670565,  0.0000000000000000,  0.7617679756965072,  0.0000000000000000,  0.6917063611214438,  0.0000000000000000,  0.1217272698758698,  0.0000000000000000,  0.1693366988903542,  0.0000000000000000,  0.7157757577569959,  0.0000000000000000,  0.4946553559543683
  VCMP_U64(12, v1,  0x0,  0x3fb9577828444dc0,  0x0,  0x3fe611ba2bf06f2a,  0x0,  0x3fe860673bd8363e,  0x0,  0x3fe6227560ee74e0,  0x0,  0x3fbf2984b325f230,  0x0,  0x3fc5acd32fdf92e8,  0x0,  0x3fe6e7a28fdabfd2,  0x0,  0x3fdfa86ef0276044);
};

// The sign injection should work with NaNs and special values, and should not raise any exceptions
void TEST_CASE5(void) {
  CLEAR_FFLAGS;
  VSET(16, e16, m1);
  CHECK_FFLAGS(0);
  VLOAD_16(v2,     0x0000,  0x3b3c,  0xb75c,  0x7fff,  0x371e,  0x3b0b,  0x30ca,  0x39d4,  0x3bf1,  0x3bf0,  0x0000,  0x3af0,  0xb1f4,  0x3b78,  0xb4bc,  0x3bbc);
  VLOAD_16(v3,     0x8000,  0xffff,  0xffff,  0xb9e8,  0xb9bc,  0x7fff,  0xb11c,  0x31de,  0x1c8f,  0xb2e3,  0x7fff,  0xb988,  0x3198,  0xbae2,  0x38de,  0x3117);
  asm volatile("vfsgnj.vv v1, v2, v3");
  VCMP_U16(13, v1, 0x8000,  0xbb3c,  0xb75c,  0xffff,  0xb71e,  0x3b0b,  0xb0ca,  0x39d4,  0x3bf1,  0xbbf0,  0x0000,  0xbaf0,  0x31f4,  0xbb78,  0x34bc,  0x3bbc);

  VSET(16, e32, m1);
  VLOAD_32(v2,     0x00000000,  0x3d816610,  0xbf536e2f,  0xbe369229,  0x3ee857e1,  0x7fffffff,  0x80000000,  0xbea51fdd,  0x3eb544da,  0xbf0d0267,  0x3dbae08b,  0xbe07ba22,  0x3f7536a6,  0x3f743637,  0x3e4badf5,  0x3f45027b);
  VLOAD_32(v3,     0x80000000,  0x7fffffff,  0x3e1626ca,  0xffffffff,  0xbefbc255,  0x7fffffff,  0xffffffff,  0xbeaff818,  0x3eada805,  0x3d96fc66,  0x3f3393e1,  0x3f5443aa,  0xbe15516c,  0xbe4c8a7b,  0xbf169fd9,  0x3f753c15);
  asm volatile("vfsgnj.vv v1, v2, v3");
  VCMP_U32(14, v1, 0x80000000,  0x3d816610,  0x3f536e2f,  0xbe369229,  0xbee857e1,  0x7fffffff,  0x80000000,  0xbea51fdd,  0x3eb544da,  0x3f0d0267,  0x3dbae08b,  0x3e07ba22,  0xbf7536a6,  0xbf743637,  0xbe4badf5,  0x3f45027b);

  VSET(16, e64, m1);
  VLOAD_64(v2,     0x0000000000000000,  0xbfee59fbc778ffbc,  0x7fffffffffffffff,  0x3fde20419edcb428,  0x8000000000000000,  0x3fa8ecd6c20a0480,  0xbfc851dfd0fdf7f8,  0xbfc784eb3b54e580,  0x3fd13e05a2db6b68,  0xbfe9790bf1eadde4,  0x3fe46b59155986dc,  0x3fcc266386bc2e10,  0x3fdb01fdd39a7d9c,  0xbfe4eef55bb6b208,  0x3fe736d06902107a,  0x3fcf3a7f44aa9f48);
  VLOAD_64(v3,     0x8000000000000000,  0x7fffffffffffffff,  0xbfe187df69e0bb9c,  0xbfe76fd3c4a3b1e8,  0x0000000000000001,  0xbfe7c6f7c1644c86,  0xbfe229ce53357d20,  0xbfe79fcc34ac1d30,  0xbfe962e04d917824,  0xbfb0aa5656314cf0,  0xbfc69c8ad7d5ef20,  0xbfddd9380f0bd244,  0xbfc408f2f3d40a40,  0xbfb01baf416f2160,  0xbfed13d1838e183a,  0xbfbee005420412c0);
  asm volatile("vfsgnj.vv v1, v2, v3");
  VCMP_U64(15, v1, 0x8000000000000000,  0x3fee59fbc778ffbc,  0xffffffffffffffff,  0xbfde20419edcb428,  0x0000000000000000,  0xbfa8ecd6c20a0480,  0xbfc851dfd0fdf7f8,  0xbfc784eb3b54e580,  0xbfd13e05a2db6b68,  0xbfe9790bf1eadde4,  0xbfe46b59155986dc,  0xbfcc266386bc2e10,  0xbfdb01fdd39a7d9c,  0xbfe4eef55bb6b208,  0xbfe736d06902107a,  0xbfcf3a7f44aa9f48);
  CHECK_FFLAGS(0);
};

int main(void) {
  enable_vec();
  enable_fp();

  TEST_CASE1();
  TEST_CASE2();
  TEST_CASE3();
  TEST_CASE4();

  TEST_CASE5();

  EXIT_CHECK();
}
